package com.supplychainapi.service.impl;

import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.joindata.inf.common.basic.exceptions.ServiceException;
import com.supplychainapi.common.RestResponse;
import com.supplychainapi.common.enums.ExceptionMessage;
import com.supplychainapi.common.enums.ParamValue;
import com.supplychainapi.dao.prod.ScmTbmaterialMapper;
import com.supplychainapi.dao.prod.ScmTbtreebuildMapper;
import com.supplychainapi.dao.prod.ScmTbunitMapper;
import com.supplychainapi.dao.prod.TbparamvalueMapper;
import com.supplychainapi.domain.MaterialList;
import com.supplychainapi.domain.MaterialListSearch;
import com.supplychainapi.domain.Rate;
import com.supplychainapi.domain.SeqNoType;
import com.supplychainapi.domain.treeBuild.TreeBuildType;
import com.supplychainapi.model.*;
import com.supplychainapi.param.ColTitle;
import com.supplychainapi.param.TbmaterialParam;
import com.supplychainapi.proxy.ValidateHelper;
import com.supplychainapi.service.*;
import com.supplychainapi.utils.*;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import tk.mybatis.mapper.entity.Example;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.UUID;

/**
 * Created by wangziqi on 2017/9/26.
 */
@Service
public class TbMaterialServiceImpl implements TbMaterialService {
    @Autowired
    ScmTbmaterialMapper tbmaterialMapper;

    @Autowired
    TbSeqNoService seqNoService;

    @Autowired
    TbUnitService unitService;

    @Autowired
    IScmTbsupplierService tbsupplierService;


    @Autowired
    TbparamvalueMapper tbparamvalueMapper;


    @Autowired
    ScmTbtreebuildMapper  tbtreebuildMapper;


    @Autowired
    ScmTbunitMapper tbunitMapper;

    @Autowired
    IScmTbstorageService tbstoragePhoneService;

    @Autowired
    private ScmTbtreebuildMapper scmTbtreebuildMapper;

    @Autowired
    IScmTbtreebuildService tbtreebuildService;


    Map<String, ScmTbunit> tbunitMap = Maps.newHashMap();

    @Override
    public RestResponse<List<ScmTbmaterial>> getAllMaterial(String shopGuid, Integer page, Integer size) {
        if(null==page)
            page=1;
        if(null==size)
            size=20;
        page=(page-1)*size;
        List<ScmTbmaterial> list = tbmaterialMapper.getAllMaterial(shopGuid, page, size);
        assembleScmTbmaterialList(list);
        return RestResponse.success(list);
    }

    @Override
    public RestResponse save(TbmaterialParam param) throws ServiceException {
        ScmTbseqno tbseqno=new ScmTbseqno();
        tbseqno.setFsCls(Constants.MATERIAL_CLASS);
        tbseqno.setFsShopGUID(param.getFsShopGUID());
        if(StringUtil.checkIsEmoji(param.getFsMaterialName())){
            throw ExceptionMessage.emoji_failed.getServiceException();
        }
        if(org.apache.commons.lang3.StringUtils.isBlank(param.getFsMaterialId())){
            param.setFsMaterialId(seqNoService.selectSeqNo(tbseqno));
            ScmTbseqno tbseqno1 = new ScmTbseqno();
            tbseqno1.setFiSeqNo(param.getFsMaterialId());
            tbseqno1.setFsCls(TreeBuildType.Material.name());
            tbseqno1.setFsShopGUID(param.getFsShopGUID());
            seqNoService.checkCode(param.getFsMaterialId(), SeqNoType.SEQNO_MATERIAL.getCode(), param.getFsShopGUID());
            seqNoService.insert(tbseqno1, param.getFsShopGUID());
        }else{
            ScmTbseqno tbseqno1=new ScmTbseqno();
            tbseqno1.setFiSeqNo(param.getFsMaterialId());
            tbseqno1.setFsCls(TreeBuildType.Material.name());
            tbseqno1.setFsShopGUID(param.getFsShopGUID());
            seqNoService.checkCode(param.getFsMaterialId(), SeqNoType.SEQNO_MATERIAL.getCode(), param.getFsShopGUID());
            seqNoService.insert(tbseqno1,param.getFsShopGUID());
        }

        ScmTbmaterial model=new ScmTbmaterial();
        BeanUtils.copyProperties(param,model);
        model.setFsCreateTime(new Date());
        model.setFsUpdateTime(new Date());
        Integer nameIsExit=    tbmaterialMapper.nameIsExit(model.getFsMaterialName(),model.getFsShopGUID());


        if(null!=nameIsExit && nameIsExit>0){

            throw ExceptionMessage.material_name_is_exit.getServiceException();
        }
        model.setFsMaterialGuId(UUID.randomUUID().toString());
        ScmTbtreebuild tbtreebuild = new ScmTbtreebuild();
        tbtreebuild.setFsShopGUID(model.getFsShopGUID());
        tbtreebuild.setFsNodeCode(model.getFsNodeCode());
        tbtreebuild.setFsTreeTypeId(TreeBuildType.Material.name());
        ScmTbtreebuild tbtreebuild1 = scmTbtreebuildMapper.selectByPrimaryKey(tbtreebuild);
        model.setFsNodeFullText(tbtreebuild1 == null ? "".concat(model.getFsMaterialName()) : tbtreebuild1.getFsNodeFullText().concat("_" + model.getFsMaterialName()));
        if (!RegexUtils.AutoCode(model.getFsMaterialId())) {
            throw ExceptionMessage.auto_code_format.getServiceException();
        }
        ValidateHelper.validate(model);
        model.setFsHelpCode(HelpCodeUtils.String2Alpha(model.getFsMaterialName()));
        int i=tbmaterialMapper.insertSelective(model);
        if(i>0){
            return RestResponse.success();
        }else{
            return RestResponse.fail(500,"操作失败");
        }
    }

    @Override
    public RestResponse update(TbmaterialParam param) throws ServiceException {
        ValidateHelper.validate(param);
        ScmTbmaterial model=new ScmTbmaterial();
        BeanUtils.copyProperties(param,model);
        model.setFsUpdateTime(new Date());
        Integer nameIsExit=    tbmaterialMapper.nameIsExit(model.getFsMaterialName(),model.getFsShopGUID());
        if(nameIsExit>1){
            throw ExceptionMessage.material_name_is_exit.getServiceException();
        }
        ScmTbmaterial tbmaterial = new ScmTbmaterial();
        tbmaterial.setFsShopGUID(param.getFsShopGUID());
        tbmaterial.setFsMaterialId(param.getFsMaterialId());
        ScmTbmaterial findDb = tbmaterialMapper.selectOne(tbmaterial);
        if (null != findDb) {
            Map<String, ScmTbtreebuild> map = tbtreebuildService.getAllByTypeAndShopGuidToMap(findDb.getFsShopGUID(), TreeBuildType.Material.name());
            String fullCode = param.getFsNodeFullCode();
            String fullText = AssembleFullText(fullCode, map);
            model.setFsNodeFullText(fullText.concat("_").concat(param.getFsMaterialName()));
        }
        model.setFsHelpCode(HelpCodeUtils.String2Alpha(model.getFsMaterialName()));
        int i=tbmaterialMapper.updateByPrimaryKeySelective(model);
        if(i>0){
            return RestResponse.success();
        }else{
            return RestResponse.fail(500,"操作失败");
        }
    }

    private String AssembleFullText(String fullCode, Map<String, ScmTbtreebuild> tbtreebuildMap) {
        StringBuffer buffer = new StringBuffer();
        String[] sz = {};
        if (StringUtils.isBlank(fullCode))
            return "";
        if (fullCode.contains("|")) {
            sz = fullCode.split("\\|");
        } else {
            sz = new String[]{fullCode};
        }
        for (String s : sz) {
            if (StringUtils.isNotBlank(s)) {
                ScmTbtreebuild tbtreebuild = tbtreebuildMap.get(s);
                if (null != tbtreebuild) {
                    buffer.append(tbtreebuild.getFsNodeText().concat("_"));
                }
            }
        }
        String str = buffer.toString();
        if (str.contains("_")) {
            return str.substring(0, str.lastIndexOf("_"));
        } else {
            return str;
        }
    }


    @Override
    public RestResponse delete(TbmaterialParam param) throws ServiceException {

        ScmTbmaterial model=new ScmTbmaterial();
        BeanUtils.copyProperties(param,model);
        model.setFsUpdateTime(new Date());
        int i=tbmaterialMapper.deleteByPrimaryKey(model);
        if(i>0){
            return RestResponse.success();
        }else{
            return RestResponse.fail(500,"操作失败");
        }
    }

    private void assembleScmTbmaterialList(List<ScmTbmaterial> list) {
        if (null != list && !list.isEmpty()) {
            TbparamvalueKey key = new TbparamvalueKey();
            key.setFsparamid(ParamValue.unitPriceAccuracy.getCode());
            key.setFsshopguid(list.get(0).getFsShopGUID());
            Tbparamvalue tbparamvalue = tbparamvalueMapper.selectByPrimaryKey(key);
            String accuracy = "2";
            if (null != tbparamvalue) {
                if (StringUtils.isNotBlank(tbparamvalue.getFsparamvalue())) {
                    accuracy = tbparamvalue.getFsparamvalue();
                }
            }
            for (ScmTbmaterial e : list) {
                if (null != e.getFdOrderPrice()) {
                    e.setFdOrderPrice(e.getFdOrderPrice().multiply(e.getFdOrderUnitRate()).setScale(Integer.valueOf(accuracy), BigDecimal.ROUND_HALF_UP));
                }
                if (null != e.getFdSalePrice()) {
                    e.setFdSalePrice(e.getFdSalePrice().multiply(e.getFdSaleUnitRate()).setScale(Integer.valueOf(accuracy), BigDecimal.ROUND_HALF_UP));
                }
                e.setFsOrderUnitName(getUnitName(e.getFsShopGUID(), e.getFsOrderUnitId()));
                e.setFsPdUnitName(getUnitName(e.getFsShopGUID(), e.getFsPdUnitId()));
                e.setFsSaleUnitName(getUnitName(e.getFsShopGUID(), e.getFsSaleUnitId()));
                e.setFsSecUnitName(getUnitName(e.getFsShopGUID(), e.getFsSecUnitId()));
                e.setFsSkUnitName(getUnitName(e.getFsShopGUID(), e.getFsSkUnitId()));
            }
        }
    }


    private void initUnitMap(String shopGuid) {
        Example example = new Example(ScmTbunit.class);
        example.createCriteria().andEqualTo("fsShopGUID", shopGuid);
        List<ScmTbunit> list = tbunitMapper.selectByExample(example);
        if (null != list && !list.isEmpty()) {
            list.stream().forEach(e -> {
                tbunitMap.put(e.getFsUnitId(), e);
            });
        }
    }

    private String getUnitName(String shopGuid, String unid) {
        if (StringUtils.isBlank(unid)) return "";
        initUnitMap(shopGuid);
        ScmTbunit tbunit = tbunitMap.get(unid);
        if (null != tbunit) {
            return tbunit.getFsUnitName();
        }
        return "";
    }
    @Override
    public RestResponse<List<ScmTbtreebuild>> selectAll(String shopGuid) throws ServiceException {
        List<ScmTbtreebuild> tbtreebuilds= tbtreebuildMapper.selectOneLevel(Constants.MATERIAL_CLASS,shopGuid);
        tbtreebuilds.stream().forEach(e->{
            List<ScmTbtreebuild> childTrees=tbtreebuildMapper.selectChild(e.getFsNodeCode(),e.getFsShopGUID());
            e.setScmTbtreebuildList(childTrees);
            e.setTbmaterials(tbmaterialMapper.selectByTreeId(e.getFsNodeCode(),e.getFsShopGUID()));
            childTrees.stream().forEach(k->{
                List<ScmTbtreebuild> trees=tbtreebuildMapper.selectChild(e.getFsNodeCode(),e.getFsShopGUID());
                k.setScmTbtreebuildList(trees);
                k.setTbmaterials(tbmaterialMapper.selectByTreeId(e.getFsNodeCode(),e.getFsShopGUID()));
            });
        });
        return RestResponse.success(tbtreebuilds);
    }

    @Override
    public RestResponse<TbmaterialParam> selectById(String shopGuid, String id) throws com.joindata.inf.common.basic.exceptions.ServiceException {
        ScmTbmaterial model=new ScmTbmaterial();
        model.setFsShopGUID(shopGuid);
        model.setFsMaterialId(id);
        ScmTbmaterial result=tbmaterialMapper.selectOne(model);
        TbmaterialParam param=new TbmaterialParam();
        if(null==result){
            throw ExceptionMessage.no_query.getServiceException();
        }

        RestResponse<ScmTbunit> unit=unitService.selectById(result.getFsShopGUID(),result.getFsUnitId());
        BeanUtils.copyProperties(result,param);
        param.setFsUnitName(unit.getData()==null?"":unit.getData().getFsUnitName());
        ScmTbsupplier tbsupplier=tbsupplierService.getSupplierInfo(result.getFsSupplierId());
        param.setFsSupplierName(tbsupplier==null?"":tbsupplier.getFsSupplierName());
        ScmTbstorage tbstorage=tbstoragePhoneService.getScmTbstorageByFsShopGUIDAndFsStorageIdInfo(result.getFsShopGUID(),result.getFsStorageId());
        param.setFsStorageName(tbstorage==null?"":tbstorage.getFsStorageName());
        ScmTbtreebuild tbtreebuild = new ScmTbtreebuild();
        tbtreebuild.setFsTreeTypeId(TreeBuildType.Material.name());
        tbtreebuild.setFsNodeCode(param.getFsNodeCode());
        tbtreebuild.setFsShopGUID(param.getFsShopGUID());
        ScmTbtreebuild tbtreebuild1 = scmTbtreebuildMapper.selectByPrimaryKey(tbtreebuild);
        param.setFsNodeText(tbtreebuild1 == null ? "" : tbtreebuild1.getFsNodeText());
        param.setFsOrderUnitName(getUnitName(param.getFsShopGUID(), param.getFsOrderUnitId()));
        param.setFsPdUnitName(getUnitName(param.getFsShopGUID(), param.getFsPdUnitId()));
        param.setFsSaleUnitName(getUnitName(param.getFsShopGUID(), param.getFsSaleUnitId()));
        param.setFsSecUnitName(getUnitName(param.getFsShopGUID(), param.getFsSecUnitId()));
        param.setFsSkUnitName(getUnitName(param.getFsShopGUID(), param.getFsSkUnitId()));
        return RestResponse.success(param);
    }

    @Override
    public RestResponse<List<ScmTbmaterial>> search(String shopGuid, String name,Integer page,Integer size) {
        if(null==page)
            page=1;
        if(null==size)
            size=20;
        page=(page-1)*size;
        return RestResponse.success(tbmaterialMapper.search(name,shopGuid,page,size));
    }

    @Override
    public RestResponse<List<ScmTbtreebuild>> getMaterialAllClass(String shopGuid) {
        List<ScmTbtreebuild>  scmTbtreebuildList =  scmTbtreebuildMapper.getScmTbtreebuildAllInfo(shopGuid,Constants.MATERIAL_CLASS);
        List<ScmTbtreebuild> resultTreeBuild = TreeUtils.buildByScmTbtreebuildTwo(scmTbtreebuildList);

        return RestResponse.success(resultTreeBuild);
    }

    @Override
    public RestResponse<List<ScmTbmaterial>> selectByClass(String shopGuid, String fsNodeCode,Integer page,Integer size) {
        if(null==page)
            page=1;
        if(null==size)
            size=20;
        page=(page-1)*size;
        List<ScmTbmaterial> list = tbmaterialMapper.selectByClass(fsNodeCode, shopGuid, page, size);
        assembleScmTbmaterialList(list);
        return RestResponse.success(list);
    }

    @Override
    public RestResponse selectByTwoClass(String shopGuid, String fsNodeCode) {
        List<ScmTbtreebuild> childTrees=tbtreebuildMapper.selectChild(fsNodeCode,shopGuid);
        childTrees.stream().forEach(e->{
            List<ScmTbmaterial> list = tbmaterialMapper.selectByTreeId(e.getFsNodeCode(), e.getFsShopGUID());
            assembleScmTbmaterialList(list);
            e.setTbmaterials(list);
        });
        if(null==childTrees || childTrees.isEmpty()){
            List<ScmTbmaterial>  list=tbmaterialMapper.selectByTreeId(fsNodeCode,shopGuid);
            assembleScmTbmaterialList(list);
            return RestResponse.success(list);
        }

        return RestResponse.success(childTrees);
    }

    @Override
    public int count(TbmaterialParam param) {
        ScmTbmaterial reod=new ScmTbmaterial();
        BeanUtils.copyProperties(param,reod);
        return tbmaterialMapper.selectCount(reod);
    }

    @Override
    public RestResponse<List<MaterialList>> pcGetAllMaterial(MaterialListSearch search) {
//        ScmTbmaterialExample example=new ScmTbmaterialExample();
//        ScmTbmaterialExample.Criteria criteria= example.createCriteria();
//        criteria.andFsShopGUIDEqualTo(search.getFsShopGuid());
//        if(StringUtils.isNotBlank(search.getKeyWords())){
//            criteria.pcListSearch(search.getKeyWords());
//        }
//
//        if(StringUtils.isNotBlank(search.getFsNodeText())){
//            criteria.pcListClass(search.getFsNodeText());
//        }
        Page<ScmTbmaterial> page=PageHelper.startPage(search.getPageNum(),search.getPageSize());
//        example.setDistinct(true);
        List<ScmTbmaterial> list=tbmaterialMapper.pcGetAllMaterial(search);
        PageInfo pageInfo=new PageInfo(page);
        List<MaterialList> result=Lists.newArrayList();
        list.stream().forEach(e->{
            MaterialList a= new MaterialList();
            BeanUtils.copyProperties(e,a);
            ScmTbunit tbunit = new ScmTbunit();
            tbunit.setFsShopGUID(a.getFsShopGUID());
            tbunit.setFsUnitId(a.getFsOrderUnitId());
            ScmTbunit orderUnit = tbunitMapper.selectByPrimaryKey(tbunit);
            a.setFsOrderUnitName(orderUnit == null ? "" : orderUnit.getFsUnitName());
            tbunit.setFsUnitId(a.getFsPdUnitId());
            ScmTbunit pdUnit = tbunitMapper.selectByPrimaryKey(tbunit);
            a.setFsPdUnitName(pdUnit == null ? "" : pdUnit.getFsUnitName());
            tbunit.setFsUnitId(a.getFsSaleUnitId());
            ScmTbunit saleUnit = tbunitMapper.selectByPrimaryKey(tbunit);
            a.setFsSaleUnitName(saleUnit == null ? "" : saleUnit.getFsUnitName());
            tbunit.setFsUnitId(a.getFsSecUnitId());
            ScmTbunit secUnit = tbunitMapper.selectByPrimaryKey(tbunit);
            a.setFsSecUnitName(secUnit == null ? "" : secUnit.getFsUnitName());
            tbunit.setFsUnitId(a.getFsSkUnitId());
            ScmTbunit skUnit = tbunitMapper.selectByPrimaryKey(tbunit);
            a.setFsSkUnitName(skUnit == null ? "" : skUnit.getFsUnitName());
//            unitService.selectById(e.getFsShopGUID(),e.)
            if(e.getFiStatus()==1){
                a.setFiStatusName("正常");
            }else if(e.getFiStatus()==9){
                a.setFiStatusName("禁用");
            }
            result.add(a);
        });
        return RestResponse.success(result, pageInfo);
    }

    @Override
    public int supplierQuotes(String shopGuid, String supplierId) {
        ScmTbmaterialExample example=new ScmTbmaterialExample();
        ScmTbmaterialExample.Criteria criteria=example.createCriteria();
        if(StringUtils.isNotBlank(shopGuid)){
            criteria.andFsShopGUIDEqualTo(shopGuid);
        }
        criteria.andFsSupplierIdEqualTo(supplierId);
        List<ScmTbmaterial> list=tbmaterialMapper.selectByExample(example);
        return list.size();
    }

    @Override
    public List<ColTitle> getSchema() {
        List<ColTitle> colTitles=Lists.newArrayList();
        colTitles.add(new ColTitle("fsMaterialId","物料代码","center",100));
        colTitles.add(new ColTitle("fsMaterialName","物料名称","center",100));
        colTitles.add(new ColTitle("fsModelno","规格型号","center",100));
        colTitles.add(new ColTitle("fsUnitName","计量单位","center",100));
        colTitles.add(new ColTitle("fsSupplierName","首选供应商名称","center",100));
        colTitles.add(new ColTitle("fiStatusName","状态","center",100));
        colTitles.add(new ColTitle("__EDIT__", "操作", null, 150, "fsMaterialId"));
        return colTitles;
    }


    @Override
    public Map<String,List<Rate>> geTrate() {
        Map<String,List<Rate>> map=Maps.newHashMap();
        List<Rate> inputTaxRate=Lists.newArrayList();
        List<Rate> salesTaxRate=Lists.newArrayList();
        List<Rate> pricingMethod=Lists.newArrayList();
        inputTaxRate.add(new Rate("0","0"));
        inputTaxRate.add(new Rate("3","3"));
        inputTaxRate.add(new Rate("6","6"));
        inputTaxRate.add(new Rate("11","11"));
        inputTaxRate.add(new Rate("13","13"));
        inputTaxRate.add(new Rate("17","17"));

        salesTaxRate.add(new Rate("0","0"));
        salesTaxRate.add(new Rate("3","3"));
        salesTaxRate.add(new Rate("6","6"));
        salesTaxRate.add(new Rate("11","11"));
        salesTaxRate.add(new Rate("13","13"));
        salesTaxRate.add(new Rate("17","17"));

        pricingMethod.add(new Rate("1","移动平均法"));
        pricingMethod.add(new Rate("2","先进先出法"));
        map.put("inputTaxRate",inputTaxRate);
        map.put("salesTaxRate",salesTaxRate);
        map.put("pricingMethod",pricingMethod);

        return map;
    }

    @Override
    public List<ColTitle> getSelectSchema() {
        List<ColTitle> colTitles = Lists.newArrayList();
        colTitles.add(new ColTitle("fsMaterialId", "物料代码", "center", 100));
        colTitles.add(new ColTitle("fsMaterialName", "物料名称", "center", 100));
        colTitles.add(new ColTitle("fsModelno", "规格型号", "center", 100));
        colTitles.add(new ColTitle("fsOrderUnitName", "采购计量单位", "center", 100));
        colTitles.add(new ColTitle("fsUnitName", "采购单价", "center", 100));
        colTitles.add(new ColTitle("fsSupplierName", "首选供应商名称", "center", 100));
        return colTitles;
    }

    @Override
    public int selectByWarehouseId(String warehouseId, String shopGuid) {
        ScmTbmaterial model = new ScmTbmaterial();
        model.setFsStorageId(warehouseId);
        model.setFsShopGUID(shopGuid);
        List list = tbmaterialMapper.select(model);
        if (null != list)
            return list.size();
        else
            return 0;
    }

    @Override
    public List<ScmTbmaterial> findFullCode(String shopGuid, String fullCode) {
        Example example = new Example(ScmTbmaterial.class);
        example.createCriteria().andEqualTo("fsShopGUID", shopGuid).andLike("fsNodeFullCode", "%".concat(fullCode).concat("%"));
        return tbmaterialMapper.selectByExample(example);
    }

    @Override
    public int updateFullTextName(ScmTbmaterial model) {
        Example example = new Example(ScmTbmaterial.class);
        example.createCriteria().andEqualTo("fsMaterialId", model.getFsMaterialId()).andEqualTo("fsShopGUID", model.getFsShopGUID());
        model.setFsNodeFullText(model.getFsNodeFullText().concat("_").concat(model.getFsMaterialName()));
        return tbmaterialMapper.updateByExampleSelective(model, example);
    }
}
